Expand description
Poem is a full-featured and easy-to-use web framework with the Rust programming language.
Table of contents
Quickstart
use poem::{get, handler, listener::TcpListener, web::Path, IntoResponse, Route, Server};
#[handler]
fn hello(Path(name): Path<String>) -> String {
format!("hello: {}", name)
}
#[tokio::main]
async fn main() -> Result<(), std::io::Error> {
let app = Route::new().at("/hello/:name", get(hello));
Server::new(TcpListener::bind("0.0.0.0:3000"))
.run(app)
.await
}
Endpoint
The Endpoint
trait represents a type that can handle HTTP requests, and
it returns the Result<T: IntoResponse, Error>
type.
The handler
macro is used to convert a function into an endpoint.
use poem::{
error::NotFoundError, handler, http::StatusCode, test::TestClient, Endpoint, Request,
Result,
};
#[handler]
fn return_str() -> &'static str {
"hello"
}
#[handler]
fn return_err() -> Result<&'static str, NotFoundError> {
Err(NotFoundError)
}
let resp = TestClient::new(return_str).get("/").send().await;
resp.assert_status_is_ok();
resp.assert_text("hello").await;
let resp = TestClient::new(return_err).get("/").send().await;
resp.assert_status(StatusCode::NOT_FOUND);
Extractors
The extractor is used to extract something from the HTTP request.
Poem
provides some commonly used extractors for
extracting something from HTTP requests.
In the following example, the index
function uses 3 extractors to extract
the remote address, HTTP method and URI.
use poem::{
handler,
http::{Method, Uri},
web::RemoteAddr,
};
#[handler]
fn index(remote_addr: &RemoteAddr, method: Method, uri: &Uri) {}
By default, the extractor will return a 400 Bad Request
when an error
occurs, but sometimes you may want to change this behavior, so you can
handle the error yourself.
In the following example, when the Query
extractor fails, it
will return a 500 Internal Server
response and the reason for the error.
use poem::{
error::ParseQueryError, handler, http::StatusCode, web::Query, IntoResponse, Response,
Result,
};
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Params {
name: String,
}
#[handler]
fn index(res: Result<Query<Params>>) -> Result<impl IntoResponse> {
match res {
Ok(Query(params)) => Ok(params.name.into_response()),
Err(err) if err.is::<ParseQueryError>() => Ok(Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(err.to_string())),
Err(err) => Err(err),
}
}
Routing
There are three available routes.
Route
Routing for pathRouteDomain
Routing for domainRouteMethod
Routing for HTTP method
use poem::{get, handler, post, web::Path, Route};
#[handler]
async fn get_user(id: Path<String>) {}
#[handler]
async fn delete_user(id: Path<String>) {}
#[handler]
async fn create_user() {}
let app = Route::new()
.at("/user/:id", get(get_user).delete(delete_user))
.at("/user", post(create_user));
You can create custom extractors, see also FromRequest
.
Responses
All types that can be converted to HTTP response Response
should
implement IntoResponse
.
In the following example, the string_response
and status_response
functions return the String
and StatusCode
types, because Poem
has
implemented the IntoResponse
trait for them.
The no_response
function does not return a value. We can think that
its return type is ()
, and Poem
also implements IntoResponse
for
()
, which is always converted to 200 OK
.
The result_response
function returns a Result
type, which means that an
error may occur.
use poem::{handler, http::StatusCode, Result};
#[handler]
fn string_response() -> String {
todo!()
}
#[handler]
fn status_response() -> StatusCode {
todo!()
}
#[handler]
fn no_response() {}
#[handler]
fn result_response() -> Result<String> {
todo!()
}
Handling errors
The following example returns customized content when
NotFoundError
occurs.
use poem::{
error::NotFoundError, handler, http::StatusCode, EndpointExt, IntoResponse, Response, Route,
};
#[handler]
fn foo() {}
#[handler]
fn bar() {}
let app =
Route::new()
.at("/foo", foo)
.at("/bar", bar)
.catch_error(|err: NotFoundError| async move {
Response::builder()
.status(StatusCode::NOT_FOUND)
.body("custom not found")
});
Middleware
You can call the with
method on the Endpoint
to
apply a middleware to an endpoint. It actually converts the original
endpoint to a new endpoint.
use poem::{handler, middleware::Tracing, EndpointExt, Route};
#[handler]
fn index() {}
let app = Route::new().at("/", index).with(Tracing);
You can create your own middleware, see also Middleware
.
Crate features
To avoid compiling unused dependencies, Poem
gates certain features, all
of which are disabled by default:
Feature | Description |
---|---|
server | Server and listener APIs(enable by default) |
compression | Support decompress request body and compress response body |
cookie | Support for Cookie |
csrf | Support for Cross-Site Request Forgery (CSRF) protection |
multipart | Support for Multipart |
native-tls | Support for HTTP server over TLS with native-tls |
openssl-tls | Support for HTTP server over TLS with openssl-tls |
opentelemetry | Support for opentelemetry |
prometheus | Support for Prometheus |
redis-session | Support for RedisSession |
rustls | Support for HTTP server over TLS with rustls |
session | Support for session |
sse | Support Server-Sent Events (SSE) |
tempfile | Support for tempfile |
test | Test utilities to test your endpoints. |
tower-compat | Adapters for tower::Layer and tower::Service . |
websocket | Support for WebSocket |
anyhow | Integrate with the anyhow crate. |
eyre06 | Integrate with version 0.6.x of the eyre crate. |
i18n | Support for internationalization |
acme-native-roots | Support for ACME(Automatic Certificate Management Environment) |
acme-webpki-roots | Support for ACME using webpki TLS roots rather than native TLS roots |
tokio-metrics | Integrate with the tokio-metrics crate. |
embed | Integrate with rust-embed crate. |
xml | Integrate with quick-xml crate. |
yaml | Integrate with serde-yaml crate. |
Re-exports
pub use endpoint::Endpoint;
pub use endpoint::EndpointExt;
pub use endpoint::IntoEndpoint;
pub use error::Error;
pub use error::Result;
pub use middleware::Middleware;
pub use web::FromRequest;
pub use web::IntoResponse;
pub use web::RequestBody;
Modules
- Endpoint related types.
- Some common error types.
- A general purpose library of common HTTP types
- i18n
i18n
Internationalization related types. - listener
server
Commonly used listeners. - Commonly used middleware.
- session
session
Session management. - test
test
Test utilities to test your endpoints. - Commonly used as the type of extractor or response.
Structs
- A body object for requests and responses.
- A future for a possible HTTP upgrade.
- Container that can be used to obtain path pattern from the request.
- Represents an HTTP request.
- An request builder.
- Component parts of an HTTP Request.
- Represents an HTTP response.
- An response builder.
- Component parts of an HTTP Response.
- Routing object
- Routing object for
HOST
header - Routing object for HTTP methods
- Routing object for request scheme
- Server
server
An HTTP Server. - An upgraded HTTP connection.
Enums
- An network address.
Functions
- A helper function, similar to
RouteMethod::new().connect(ep)
. - A helper function, similar to
RouteMethod::new().delete(ep)
. - A helper function, similar to
RouteMethod::new().get(ep)
. - A helper function, similar to
RouteMethod::new().head(ep)
. - A helper function, similar to
RouteMethod::new().options(ep)
. - A helper function, similar to
RouteMethod::new().patch(ep)
. - A helper function, similar to
RouteMethod::new().post(ep)
. - A helper function, similar to
RouteMethod::new().put(ep)
. - A helper function, similar to
RouteMethod::new().trace(ep)
.
Attribute Macros
- Wrap an asynchronous function as an
Endpoint
.